
#include "ql.h"
#include <stdarg.h>

/*
 * definitions  to nil/t elements
 */

/*
 * nil object IS THE SAME AS AN EMPTY LIST!
 */
static List
g_nil_obj_def =
{
    OBJ_NIL,
    0, /* car */
    0, /* cdr */
};

static Obj
g_t_obj_def =
{
    OBJ_T,
};

Obj *   g_nil_obj = (Obj *)&g_nil_obj_def;
Obj *   g_t_obj = &g_t_obj_def;


List * alloc_listv( AllocContext * c, Obj * arg1, ... )
{
    List *          result = alloc_list( c );

    if( arg1 != 0 )
    {
        List **     last_cdr = &result->cdr;
        va_list     ap;
        
        result->car = arg1;        
        va_start( ap, arg1 );

        for( ;; )
        {
            Obj *   argN = va_arg( ap, Obj * );
            List *  cdr;

            if( 0 == argN )
            {
                break;
            }
            
            cdr = alloc_list( c );
            cdr->car = (Obj *)argN;
            
            *last_cdr = cdr;
            last_cdr = &cdr->cdr;
        }

        va_end( ap );
    }

    return result;
}

List * alloc_listn( AllocContext * c, Obj ** obj_array, size_t obj_array_size )
{
    List *      result = alloc_list( c );

    if( obj_array_size > 0 )
    {
        List ** last_cdr = &result->cdr;
        size_t  n;

        result->car = obj_array[0];

        for( n = 1; n < obj_array_size; ++ n )
        {
            List * cdr = alloc_list( c );
            cdr->car = obj_array[n];
            
            *last_cdr = cdr;
            last_cdr = &cdr->cdr;
        }
    }

    return result;
}

/*
 * helper free function
 */
void free_list_chain(
    AllocContext *  c,
    List *          list,
    void (* free_node_p)(void *, Obj *),
    void *          tag
    )
{
    while( list != 0 )
    {
        List *    next_list = list->cdr;

        if( free_node_p != 0 )
        {
            free_node_p( tag, list->car );
        }

        free_list( c, list );
        list = next_list;
    }
}

